/**
 * 2017年11月16日
 */
package exp.algorithm.sic.scalerf;

import java.util.Random;

import exp.algorithm.sic.scalerf.fea.FeatureFactory;
import exp.algorithm.sic.scalerf.fea.FeatureSet;
import exp.algorithm.sic.scalerf.fea.FeatureType;
import exp.core.InstancesLoader;
import exp.util.DatasetsUtil;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;

/**
 * @author Alex
 *
 */
public class RandomSelectIntervalConverter implements IntervalSelector  {

	public static void main(String[] args) {
		IntervalSelector rf = new RandomSelectIntervalConverter();
		InstancesLoader il = new InstancesLoader();
		Instances inst = il.loadTrain("Gun_Point");
		Instances insts = rf.transform(inst);
		Instance in = rf.transform(inst.instance(0));
		in.attribute(0);
	}
	
	//有多少个基分类器
	int numTrees = 500;
	FeatureType ft = null;
	FeatureFactory ff = null;
	
	int numFeatures;
	int[][][] intervals;
	Random rand = new Random(47L);
	
	Instances testHolder;
	public RandomSelectIntervalConverter() {
		this(FeatureType.TSF);
	}
	public RandomSelectIntervalConverter(FeatureType ft){
		this.ft = ft;
		ff = FeatureFactory.buildFactory(ft);
	}
	
	@Override
	public Instance transform(Instance ins){
		// Build instance
		double[] series = ins.toDoubleArray();
		for (int i = 0; i < numTrees; i++) {
			for (int j = 0; j < numFeatures; j++) {
				// extract the interval
				FeatureSet f = ff.newInstance();
				f.setFeatures(series, intervals[i][j][0], intervals[i][j][1]);
				testHolder.instance(0).setValue(j * 3, f.get(0));
				testHolder.instance(0).setValue(j * 3 + 1, f.get(1));
				testHolder.instance(0).setValue(j * 3 + 2, f.get(2));
			}
		}
		return testHolder.instance(0);
	}
	
	@Override
	public Instances transform(Instances data){
		numFeatures = (int) Math.sqrt(data.numAttributes() - 1);
		intervals = new int[numTrees][][];
		Attribute target = data.attribute(data.classIndex());
		Instances result = DatasetsUtil.initInstancesWithParmas("Tree", numFeatures*3, "F_", data.numInstances(), true, target);
		testHolder = new Instances(result,0);
		for (int i = 0; i < data.numInstances(); i++) {
			DenseInstance in = new DenseInstance(result.numAttributes());
			in.setValue(result.numAttributes() - 1, data.instance(i).classValue());
			result.add(in);
		}
		DenseInstance in = new DenseInstance(result.numAttributes());
		testHolder.add(in);
		// For each tree
		for (int i = 0; i < numTrees; i++) {
			// 1. Select random intervals for tree i
			// TO DO: this may not be as published
			// IN CODE: inx = randsample(size(X,1),ceil(size(X,1)*2/2),1);%1:
			// with replacement; 0: without replacement
			intervals[i] = new int[numFeatures][2]; // Start and end
			for (int j = 0; j < numFeatures; j++) {
				intervals[i][j][0] = rand.nextInt(data.numAttributes() - 1); // Start
				int length = rand.nextInt(data.numAttributes() - 1 - intervals[i][j][0]);// Min
				intervals[i][j][1] = intervals[i][j][0] + length;
			}
			// 2. Generate and store random attributes
			for (int j = 0; j < numFeatures; j++) {
				// For each instance
				for (int k = 0; k < data.numInstances(); k++) {
					// extract the interval
					double[] series = data.instance(k).toDoubleArray();
					FeatureSet f = ff.newInstance();
					f.setFeatures(series, intervals[i][j][0], intervals[i][j][1]);
					result.instance(k).setValue(j * 3, f.get(0));
					result.instance(k).setValue(j * 3 + 1, f.get(1));
					result.instance(k).setValue(j * 3 + 2, f.get(2));
				}
			}
		}
		return result;
	}
}	
